﻿using System.Collections.Generic;
using UnityEngine;

namespace TC
{
    public class BTFlow : Dispatcher
    {
        public List<FlowNode> change;
        public FlowNode cur;
        public int curIndex;

        public override void OnNodeChange(FlowNode node)
        {
            change.Add(node);
        }

        private bool hasNode(FlowNode node)
        {
            foreach (var i in callstack)
            {
                if (i == node) { return true; }
            }
            return false;
        }

        public override void Destroy()
        {
            FlowNode tmp = null;
            int i = 0;
            while (callstack.Count > 0)
            {
                i = callstack.Count - 1;
                tmp = callstack[i];
                callstack.RemoveAt(i);
                if (tmp is IRepeat)
                {
                    if (!hasNode(tmp))
                    {
                        tmp.Stop();
                    }
                }
                else
                {
                    tmp.Stop();
                }
            }
            cur = null;
            curIndex = -1;
            change.Clear();
            onComplete = null;
        }

        public override void Update(float delta)
        {
            //
            foreach (var item in callstack)
            {
                if (item is IUpdate)
                {
                    (item as IUpdate).OnUpdate(delta);
                }
            }

            int i;
            for (i = 0; i < callstack.Count; ++i)
            {
                foreach (var j in change)
                {
                    if (callstack[i] == j)
                    {
                        break;
                    }
                }
            }

            change.Clear();
            if (i < callstack.Count)
            {
                cur = callstack[i];
                //把优先级最高的节点后面的所有入栈节点都pop
                pop(i);

                //再入栈
                curIndex = callstack.Count;
                push(cur);
                cur.Execute(this);
            }
        }

        public override void Call(FlowPort p)
        {
#if UNITY_EDITOR
            if (p.parent.HasBreak)
                Debug.Break();
#endif

            Port other = p.parent.graph.GetConnect(p);
            if (other == null)
            {
                End(0);
            }
            else
            {
                cur = other.parent;
                curIndex = callstack.Count;
                push(cur);
                cur.Execute(this);
            }
        }

        public override void End(int status)
        {
            if (cur is IPopChild)
            {
                pop(curIndex);
            }

            FlowNode tmp = null;
            for (int i = curIndex - 1; i >= 0; --i)
            {
                tmp = callstack[i];
                if (tmp is IRepeat)
                {
                    cur = tmp;//
                    if (cur is IBack)//重复入栈
                    {
                        curIndex = callstack.Count;
                        push(cur);
                    }
                    else
                    {
                        curIndex = i;
                    }
                    (cur as IRepeat).Next(status);
                    return;
                }
            }

            //如果没有找到，说明某个节点下面的子树都完成了，这时向上返回end
            cur = null;
            onComplete(status);
        }
    }
}
